package com.mycp.privacy.transformers

import com.didiglobal.booster.kotlinx.file
import com.didiglobal.booster.kotlinx.touch
import com.didiglobal.booster.transform.TransformContext
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodInsnNode
import java.io.PrintWriter
import java.text.SimpleDateFormat
import java.util.*
import kotlin.collections.HashMap


/**
 * @author: liujie
 * @date: 2022/8/23 上午11:34
 * @description:  用于处理替换隐私函数的转换类
 */
class PrivacyMethodReplaceTransform : InterceptTransformer() {
    private lateinit var logger: PrintWriter
    private val asmItems = AnnotationParserClassTransform.asmConfigs
    private var asmItemsClassMap: HashMap<String, String> = HashMap<String, String>()
    private var index = 1

    @Suppress("SimpleDateFormat")
    override fun onPreTransform(context: TransformContext) {
        super.onPreTransform(context)
        this.logger = context.reportsDir.file("PrivacyMethodReplaceTransform").file(context.name)
            .file("my-privacy-report.txt").touch().printWriter()
        logger.println("--start-- ${SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Date())}")

        AnnotationParserClassTransform.asmConfigs.forEach {
            asmItemsClassMap[it.targetClass] = it.targetClass
        }
        logger.print("\nasmItemsMap size=${asmItemsClassMap.size}，asmItems.size=${asmItems.size}\n\n")
        logger.print("asmItemsClassMap=${asmItemsClassMap} \n\n")
        asmItems.forEach {
            logger.print("收集的自定义隐私函数=${it} \n\n")
        }
        println("\nasmItemsMap size=${asmItemsClassMap.size}，asmItems.size=${asmItems.size}\n\n")
        println("asmItemsClassMap=${asmItemsClassMap} \n\n")
        println("asmItems=${asmItems} \n\n")
    }

    @Suppress("SimpleDateFormat")
    override fun onPostTransform(context: TransformContext) {
        logger.println("\n --end-- ${SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(Date())}")
        this.logger.close()
    }

    override fun transform(context: TransformContext, klass: ClassNode) = klass.also {

//        if (onCommInterceptor(context, klass)) {
//            return klass
//        }
        //排除系统函数
        if (klass.name == "android/support/v7/app/TwilightManager"){
            return@also
        }
        if (klass.name.startsWith("android/support/v4")){
            return@also
        }
        if (klass.name.startsWith("androidx/core")){
            return@also
        }
        if (AnnotationParserClassTransform.asmConfigsMap.contains(klass.name)) {
            logger.print("\n忽略自定义隐私类=${klass.name}\n")
            return@also
        }

        klass.methods.forEach { method ->
            method.instructions?.iterator()?.forEach { insnNode ->

                if (insnNode is MethodInsnNode) {
                    asmItems.forEach { asmItem ->
                        if (asmItem.oriDesc == insnNode.desc && asmItem.oriMethod == insnNode.name
                            && insnNode.opcode == asmItem.oriAccess &&
                            (insnNode.owner == asmItem.oriClass || asmItem.oriClass == "java/lang/Object")
                        ) {

                            logger.print(
                                "\n替换隐私函数调用信息$index:\n" +
                                        "目标的类和函数：   name=${klass.name}#${insnNode.name}--> opcode=${insnNode.opcode},--> desc=${insnNode.owner}${insnNode.desc} ->\n" +
                                        "自定义类和函数：   name=${asmItem.targetClass}#${asmItem.targetMethod}--> opcode=${asmItem.targetAccess},--> desc=${asmItem.targetDesc} ->\n"
                            )
                            println(
                                "\n替换隐私函数调用信息$index:\n" +
                                        "目标的类和函数：   name=${klass.name}#${insnNode.name}--> opcode=${insnNode.opcode},--> desc=${insnNode.owner}${insnNode.desc} ->\n" +
                                        "自定义类和函数：   name=${asmItem.targetClass}#${asmItem.targetMethod}--> opcode=${asmItem.targetAccess},--> desc=${asmItem.targetDesc} ->\n"
                            )
                            insnNode.opcode = asmItem.targetAccess
                            insnNode.desc = asmItem.targetDesc
                            insnNode.owner = asmItem.targetClass
                            insnNode.name = asmItem.targetMethod
                            index++
                        }
                    }
                }
            }
        }
    }


}